package tr.edu.metu.is.mega.client.schedule;

import java.util.List;

import tr.edu.metu.is.mega.client.core.DialogCallbackAdapter;
import tr.edu.metu.is.mega.client.core.MainWindow;
import tr.edu.metu.is.mega.client.resource.MEGAIconBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResourceBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResources;
import tr.edu.metu.is.mega.client.service.GwtScheduleService;
import tr.edu.metu.is.mega.client.service.GwtScheduleServiceAsync;
import tr.edu.metu.is.mega.client.widgets.MegaTextField;
import tr.edu.metu.is.mega.common.dto.ActivityTemplateDTO;
import tr.edu.metu.is.mega.common.dto.ScheduleTemplateDTO;

import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.ColumnData;
import com.extjs.gxt.ui.client.widget.layout.ColumnLayout;
import com.extjs.gxt.ui.client.widget.layout.FillLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.extjs.gxt.ui.client.widget.layout.RowData;
import com.extjs.gxt.ui.client.widget.layout.RowLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * Main window to manage schedule templates.
 */
public class ScheduleTemplateManagementWindow extends MainWindow {

    private final MEGAResourceBundle resourceBundle = MEGAResources.RESOURCEBUNDLE;

    private final MEGAIconBundle iconBundle = MEGAResources.ICONBUNDLE;

    private ActivityTemplatePanel activityTemplatePanel;

    private MegaTextField nameField;

    private MegaTextField descriptionField;

    private ScheduleTemplateDTO scheduleTemplate;

    /**
     * Default constructor.
     */
    public ScheduleTemplateManagementWindow() {
        super("ScheduleTemplateManagementWindow", ScheduleTemplateDTO.class.getName());
        setHeading(resourceBundle.scheduleTemplateHeader());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onRender(Element parent, int pos) {
        super.onRender(parent, pos);
        setLayout(new FillLayout());

        ContentPanel panel = new ContentPanel(new RowLayout());
        panel.setHeaderVisible(false);

        LayoutContainer topPanel = new LayoutContainer(new ColumnLayout());
        topPanel.setStyleAttribute("padding", "10px");

        LayoutContainer left = new LayoutContainer(new FormLayout());
        nameField = new MegaTextField(ScheduleTemplateDTO.FIELD_SHORT_NAME);
        nameField.setFieldLabel(resourceBundle.scheduleTemplateShortName());
        left.add(nameField, new FormData("96%"));

        LayoutContainer right = new LayoutContainer(new FormLayout());
        descriptionField = new MegaTextField(ScheduleTemplateDTO.FIELD_DESCRIPTION);
        descriptionField.setFieldLabel(resourceBundle.scheduleTemplateDescription());
        right.add(descriptionField, new FormData("96%"));

        topPanel.add(left, new ColumnData(0.3));
        topPanel.add(right, new ColumnData(0.7));

        activityTemplatePanel = new ActivityTemplatePanel();

        panel.add(topPanel);
        panel.add(activityTemplatePanel, new RowData(1, -1, new Margins(10, 10, 0, 10)));

        panel.setTopComponent(getToolBar());

        add(panel);
    }

    /**
     * Initializes and returns toolbar.
     * 
     * @return toolbar
     */
    private ToolBar getToolBar() {
        ToolBar toolBar = new ToolBar();
        toolBar.setMinButtonWidth(70);
        toolBar.setSpacing(5);

        final Button saveButton = new Button(resourceBundle.save(), AbstractImagePrototype.create(iconBundle.save()));
        saveButton.setEnabled(false);
        saveButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                try {
                    ScheduleTemplateDTO guiToDTO = guiToDTO();

                    if (scheduleTemplate != null && scheduleTemplate.getPkid() != null) {
                        getService().updateSchedule(guiToDTO, new AsyncCallback<ScheduleTemplateDTO>() {

                            @Override
                            public void onSuccess(ScheduleTemplateDTO result) {
                                Info.display("", "Updated");
                            }

                            @Override
                            public void onFailure(Throwable caught) {
                                Info.display("", "Failed");
                            }
                        });
                    } else {
                        getService().createSchedule(guiToDTO, new AsyncCallback<ScheduleTemplateDTO>() {

                            @Override
                            public void onSuccess(ScheduleTemplateDTO result) {
                                Info.display("", "Saved");
                            }

                            @Override
                            public void onFailure(Throwable caught) {
                                Info.display("", "Failed");
                            }
                        });
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        });

        Button selectButton = new Button(resourceBundle.select(), AbstractImagePrototype.create(iconBundle.select()));
        selectButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                ScheduleTemplateSelectDialog dialog = new ScheduleTemplateSelectDialog(false, false);
                dialog.select(new DialogCallbackAdapter<ScheduleTemplateDTO>() {

                    @Override
                    public void onOk(ScheduleTemplateDTO param) {
                        dtoToGUI(param);
                        saveButton.setEnabled(true);
                    }
                });

            }
        });

        Button deleteButton = new Button(resourceBundle.delete(), AbstractImagePrototype.create(iconBundle.delete()));
        deleteButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (scheduleTemplate != null)
                    getService().deleteSchedule(scheduleTemplate, new AsyncCallback<Void>() {

                        @Override
                        public void onSuccess(Void result) {
                            Info.display("", "Deleted");
                        }

                        @Override
                        public void onFailure(Throwable caught) {
                            Info.display("", "Failed");
                        }
                    });

            }
        });

        Button newButton = new Button(resourceBundle.newS(), AbstractImagePrototype.create(iconBundle.add()));
        newButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                clear();
                saveButton.setEnabled(true);
            }
        });

        toolBar.add(selectButton);
        toolBar.add(newButton);
        toolBar.add(deleteButton);
        toolBar.add(saveButton);

        return toolBar;
    }

    /**
     * Getter for async service.
     * 
     * @return {@link GwtScheduleServiceAsync}
     */
    public static GwtScheduleServiceAsync getService() {
        return GwtScheduleService.Util.getInstance();
    }

    /**
     * Generates DTO instance from GUI widgets.
     * 
     * @return DTO instance
     */
    private ScheduleTemplateDTO guiToDTO() {
        if (!nameField.isValid() || !descriptionField.isValid()) {
            MessageBox.info("Warning", "Check fields", null);
            throw new RuntimeException("Fields are not valid");
        } else {
            List<ActivityTemplateDTO> activities = activityTemplatePanel.getActivities();
            if (activities.size() == 0) {
                MessageBox.info("Warning", "You should add at least one activity", null);
                throw new RuntimeException("Fields are not valid");
            }

            if (scheduleTemplate != null) {
                int id = scheduleTemplate.getPkid();
                scheduleTemplate = new ScheduleTemplateDTO();
                scheduleTemplate.setPkid(id);
            } else {
                scheduleTemplate = new ScheduleTemplateDTO();
            }
            scheduleTemplate.setShortname(nameField.getValue());
            scheduleTemplate.setDescription(descriptionField.getValue());
            scheduleTemplate.setActivities(activityTemplatePanel.getActivities());
            return scheduleTemplate;
        }
    }

    /**
     * Displays a DTO instance.
     * 
     * @param dto DTO instance
     */
    private void dtoToGUI(ScheduleTemplateDTO dto) {
        scheduleTemplate = dto;
        nameField.setValue(dto.getShortname());
        descriptionField.setValue(dto.getDescription());
        activityTemplatePanel.setActivities(dto.getActivities());
    }

    /**
     * Clears the screen.
     */
    private void clear() {
        scheduleTemplate = null;
        nameField.clear();
        descriptionField.clear();
        activityTemplatePanel.clear();
    }
}
